ReedSolomon question (2007-03-22 11:29 by Anonyme #28522)
I compared ReedSolomon.java with the code from http://sourceforge.net/projects/rscode/, and found a difference.
--> in decode_data() & Modified_Berlekamp_Massey(), the original NPAR is replaced by 8(==MAXDEG).
--> and during my decoding of camera scanned picture, I found the error correction in ReedSolomon.java cannot correct all errors and sometime give wrong result. Anybody can solve the problem?
//G(x)=P^8+P^4+P^3+P^2+1
int[] y;
int NPAR;
int MAXDEG;
int[] synBytes;
// The Error Locator Polynomial, also known as Lambda or Sigma. Lambda[0] == 1
int[] Lambda;
// The Error Evaluator Polynomial
int[] Omega;
// local ANSI declarations
// error locations found using Chien's search
int[] ErrorLocs = new int[256];
int NErrors;
// erasure flags
int[] ErasureLocs = new int[256];
int NErasures = 0;
/* multiplication using logarithms */
int gmult(int a, int b) {
if (a==0 || b == 0) return (0);
int i = glog[a];
int j = glog[b];
int k = (i + j) % (255);
//System.out.println("i=" + i + " j=" + j + " gexp[k]=" + gexp[k]);
return (gexp[k]);
}
int ginv (int elt) {
return (gexp[255-glog[elt]]);
}
public ReedSolomon(int[] source, int aNPAR) {
y = source;
NPAR = aNPAR;
MAXDEG = NPAR * 2;
synBytes = new int[MAXDEG];
Lambda = new int[MAXDEG];
Omega = new int[MAXDEG];
}
void decode_data(int[] data) {
int sum;
for (int j = 0; j < NPAR; j++) {
sum = 0;
//System.out.println("gexp[j+1]=" + gexp[j+1]);
for (int i = 0; i < data.length; i++) {
sum = data[i] ^ gmult(gexp[j+1], sum);
//System.out.println("sum=" + sum);
}
synBytes[j] = sum;
//System.out.println("synBytes["+j+"]="+synBytes[j]);
}
}
public void correct() {
decode_data(y);
boolean hasError = false;
for (int i = 0; i < NPAR; i++) {
//System.out.println("synBytes[" + i + "] = " + synBytes[i]);
if (synBytes[i] != 0) hasError = true;
}
if (hasError) {
correct_errors_erasures (y, y.length, 0, new int[1]);
}
}
public int getNumCorrectedErrors() {
return NErrors;
}
/* From Cain, Clark, "Error-Correction Coding For Digital Communications", pp. 216. */
void Modified_Berlekamp_Massey () {
int n, L, L2, k, d, i;
int[] psi = new int[MAXDEG];
int[] psi2 = new int[MAXDEG];
int[] D = new int[MAXDEG];
int[] gamma = new int[MAXDEG];
/* initialize Gamma, the erasure locator polynomial */
init_gamma(gamma);
/* initialize to z */
copy_poly(D, gamma);
mul_z_poly(D);
copy_poly(psi, gamma);
k = -1; L = NErasures;
for (n = NErasures; n < NPAR; n++) {
d = compute_discrepancy(psi, synBytes, L, n);
//System.out.println("n=" + n + " d=" + d);
if (d != 0) {
/* psi2 = psi - d*D */
for (i = 0; i < MAXDEG; i++) psi2[i] = psi[i] ^ gmult(d, D[i]);
if (L < (n-k)) {
L2 = n-k;
k = n-L;
/* D = scale_poly(ginv(d), psi); */
for (i = 0; i < MAXDEG; i++) D[i] = gmult(psi[i], ginv(d));
L = L2;
}
/* psi = psi2 */
for (i = 0; i < MAXDEG; i++) psi[i] = psi2[i];
}
mul_z_poly(D);
}
for(i = 0; i < MAXDEG; i++) Lambda[i] = psi[i];
compute_modified_omega();
}
/* given Psi (called Lambda in Modified_Berlekamp_Massey) and synBytes,
compute the combined erasure/error evaluator polynomial as
Psi*S mod z^4
*/
void compute_modified_omega () {
int[] product = new int[MAXDEG*2];
mult_polys(product, Lambda, synBytes);
zero_poly(Omega);
for(int i = 0; i < NPAR; i++) Omega[i] = product[i];
}
/* polynomial multiplication */
void mult_polys (int[] dst, int[] p1, int[] p2) {
int i, j;
int[] tmp1 = new int[MAXDEG*2];
for (i = 0; i < (MAXDEG*2); i++) dst[i] = 0;
for (i = 0; i < MAXDEG; i++) {
for(j=MAXDEG; j<(MAXDEG*2); j++) tmp1[j]=0;
/* gamma = product (1-z*a^Ij) for erasure locs Ij */
void init_gamma (int[] gamma) {
int[] tmp = new int[MAXDEG];
zero_poly(gamma);
zero_poly(tmp);
gamma[0] = 1;
for (int e = 0; e < NErasures; e++) {
copy_poly(tmp, gamma);
scale_poly(gexp[ErasureLocs[e]], tmp);
mul_z_poly(tmp);
add_polys(gamma, tmp);
}
}
void compute_next_omega (int d, int[] A, int[] dst, int[] src) {
for (int i = 0; i < MAXDEG; i++) {
dst[i] = src[i] ^ gmult(d, A[i]);
}
}
int compute_discrepancy (int[] lambda, int[] S, int L, int n) {
int sum=0;
for (int i = 0; i <= L; i++)
sum ^= gmult(lambda[i], S[n-i]);
return (sum);
}
/********** polynomial arithmetic *******************/
void add_polys (int[] dst, int[] src) {
for (int i = 0; i < MAXDEG; i++) dst[i] ^= src[i];
}
void copy_poly (int[] dst, int[] src) {
for (int i = 0; i < MAXDEG; i++) dst[i] = src[i];
}
void scale_poly (int k, int[] poly) {
for (int i = 0; i < MAXDEG; i++) poly[i] = gmult(k, poly[i]);
}
void zero_poly (int[] poly) {
for (int i = 0; i < MAXDEG; i++) poly[i] = 0;
}
/* multiply by z, i.e., shift right by 1 */
void mul_z_poly (int[] src) {
for (int i = MAXDEG-1; i > 0; i--) src[i] = src[i-1];
src[0] = 0;
}
/* Finds all the roots of an error-locator polynomial with coefficients
* Lambda[j] by evaluating Lambda at successive values of alpha.
*
* This can be tested with the decoder's equations case.
*/
void Find_Roots () {
int sum;
NErrors = 0;
for (int r = 1; r < 256; r++) {
sum = 0;
/* evaluate lambda at r */
for (int k = 0; k < NPAR+1; k++) {
sum ^= gmult(gexp[(k*r)%255], Lambda[k]);
//System.out.println("r: " + r + " k: " + k + " sum: " + sum);
}
if (sum == 0) {
ErrorLocs[NErrors] = (255-r);
NErrors++;
//System.out.println("Root found at r = " + r + "(255-r) = " + (255-r));
}
}
}
/* Combined Erasure And Error Magnitude Computation
*
* Pass in the codeword, its size in bytes, as well as
* an array of any known erasure locations, along the number
* of these erasures.
*
* Evaluate Omega(actually Psi)/Lambda' at the roots
* alpha^(-i) for error locs i.
*
* Returns 1 if everything ok, or 0 if an out-of-bounds error is found
*
*/
int correct_errors_erasures (int[] codeword, int csize, int nerasures, int[] erasures) {
int r, i, j, err;
/* If you want to take advantage of erasure correction, be sure to
set NErasures and ErasureLocs[] with the locations of erasures.
*/
NErasures = nerasures;
for (i = 0; i < NErasures; i++) ErasureLocs[i] = erasures[i];
Modified_Berlekamp_Massey();
Find_Roots();
//System.out.println("NErrors: " + NErrors);
if ((NErrors <= NPAR) && NErrors > 0) {
/* first check for illegal error locs */
for (r = 0; r < NErrors; r++) {
if (ErrorLocs[r] >= csize) {
//System.out.println("ErrorLocs[" + r + "]: " + ErrorLocs[r]);
//return(0);
}
}
for (r = 0; r < NErrors; r++) {
int num, denom;
i = ErrorLocs[r];
/* evaluate Omega at alpha^(-i) */
num = 0;
for (j = 0; j < MAXDEG; j++)
num ^= gmult(Omega[j], gexp[((255-i)*j)%255]);
RE: ReedSolomon question (2007-07-02 16:47 by jascco #30412)
Hi all,
Tried to apply this correction to code. But in my case it doesen't help. I
I have encoded string TestString! to my qrcode when it has no errors decode results is same. But when apply two errors to image it gives me result TestSuring!
If I do some debugging I see that erros have not been found.
RE: ReedSolomon question (2007-09-03 23:54 by drhu00 #31992)
Hi, jascco
I think I find the bug of reedsolomon. Please send me your test images and let me verify it.
you can send to drhu00@yahoo.com
If it is ok, I'll send the code to Yanbe.