//matrix determinent //the original matrix is saved in stead of destoryed, so the copy of //matrix is used double Matrix::det(void) { McoStatus status; int32 i, j, k; double **max, **temp; double returnval; //if not a square matrix, return singular error if( _row != _col){ _set_status(MCO_SINGULAR); return 0; } max = (double**)McoMalloc(sizeof( double*)*_row); if(!max){ _set_status(MCO_MEM_ALLOC_ERROR); return 0; } for( j = 0; j < _row; j++){ max[j] = (double*)McoMalloc(sizeof(double)*_col); if(!max[j]){ _set_status(MCO_MEM_ALLOC_ERROR); for(k = j-1; k >= 0; k--) McoFree((void *) max[k]); McoFree((void *) max); return 0.0; } } //copy the original matrix for( i = 0; i < _row; i++) for( j = 0; j < _col; j++) max[i][j] = _m[i][j]; temp = _m; _m = max; status = _ludcmp(); if(status != MCO_SUCCESS){ //singular matrix, everything assigned to 0 returnval = 0.0; } else { returnval = _m[0][0]; for( i = 1; i < _row; i++) returnval *= _m[i][i]; } for( i = 0; i < _row; i++) McoFree((void *) _m[i]); McoFree((void *) _m); _m = temp; return returnval; }
//transverse of matrix Matrix& Matrix::T(void) { int32 i,j; double ** newm; double tempval; //added on 8/12 to take out smatrix class if( _row == _col){ for(i = 0; i < _row; i++){ for(j = i; j < _col; j++){ tempval = _m[i][j]; _m[i][j] = _m[j][i]; _m[j][i] = tempval; } } return *this; } //end of modification newm = (double**)McoMalloc(sizeof(double*)*_col); if(!newm){ _set_status(MCO_MEM_ALLOC_ERROR); return *this; } for(i = 0; i < _col; i++){ newm[i] = (double*)McoMalloc(sizeof(double)*_row); if(!newm[i]){ for(j = i-1; j >= 0; j--) McoFree((void *) newm[j]); McoFree((void *) newm); } } for( i = 0; i < _row; i++){ for(j = 0; j < _col; j++){ newm[j][i] = _m[i][j]; } } for(i = 0; i < _row; i++){ McoFree((void *) _m[i]); } McoFree((void *) _m); _m = newm; int32 temprow = _col; _col = _row; _row = temprow; return *this; }
McoStatus ScanSimpleCal::calibrate(long size, double *mea, double *ref) { McoStatus status; long i, j, k, m; double avg, max; int32 which; long calsize; //the number of patches used to calibrate double *desmea, *desref; double *cyanmea, *cyanref; //init _cleanup(); _num_data = size; //matrix computation Matrix matconv(3); double mat[9]; mat[0] = 0.5242/2.55; mat[1] = 0.3083/2.55; mat[2] = 0.1316/2.55; mat[3] = 0.2851/2.55; mat[4] = 0.6554/2.55; mat[5] = 0.0594/2.55; mat[6] = 0.0293/2.55; mat[7] = 0.1377/2.55; mat[8] = 0.6578/2.55; matconv.loadstruct(mat); matconv.inv(); status = matconv.get_status(); if(status != MCO_SUCCESS) return status; desmea = (double*)McoMalloc(sizeof(double)*_num_data*3); if(!desmea) return MCO_MEM_ALLOC_ERROR; desref = (double*)McoMalloc(sizeof(double)*_num_data*3); if(!desref) return MCO_MEM_ALLOC_ERROR; for(j = 0; j < _num_data*3; j++) { desmea[j] = mea[j]; desref[j] = ref[j]; } //create global calibration status = _globalcal(matconv, _num_data, desmea, ref); if(status != MCO_SUCCESS) return status; McoFree(desmea); McoFree(desref); return status; }
void Matrix::_deallocate(void) { if(_m){ for(int32 i = 0; i < _row; i++){ McoFree((void *) _m[i]); } McoFree((void *) _m); _m = 0; } //modified on 8/12 to take out smatrix class //for square matrix, also need to deallocate for the //additional memory if(_indx){ McoFree((void *) _indx); _indx = 0; } }
//_row and _col must be set before calling this method void Matrix::_allocate(void) { _m = (double**)McoMalloc(sizeof(double*)*_row); if(!_m) _err = MCO_MEM_ALLOC_ERROR; else{ for(int32 i = 0; i < _row; i++){ _m[i] = (double*)McoMalloc(sizeof(double)*_col); if(!_m[i]){ //not enough memory for(int32 j = i-1; j >= 0; j--) McoFree((void *) _m[j]); McoFree((void *) _m); _m = 0; _err = MCO_MEM_ALLOC_ERROR; break; } } } //modified on 8/12 to take out smatrix class //for square matrix, also need to allocate for the //additional memory _indx = 0; if( _row == _col){ if(_err == MCO_SUCCESS){ _indx = (double*)McoMalloc(sizeof(double)*_row); if(!_indx){ _deallocate(); _err = MCO_MEM_ALLOC_ERROR; return; } } } //end of modification }
McoStatus ScanCal::_linearstrech(int32 num_linear, PWlinear **linear, int32 num_data, double* data) { long i, j; double *rgb; rgb = (double*)McoMalloc(sizeof(double)*num_data); if(!rgb) return MCO_MEM_ALLOC_ERROR; for(i = 0; i < num_linear; i++){ for(j = 0; j < num_data; j++) rgb[j] = data[j*num_linear + i]; linear[i]->apply(num_data, rgb); for(j = 0; j < num_data; j++) data[j*num_linear + i] = rgb[j]; } McoFree(rgb); return MCO_SUCCESS; }
void clear_debug(void) { current_level = -1; if (dbg_new_ptrs) McoFree(dbg_new_ptrs); dbg_new_ptrs = 0L; if (dbg_new_sizes) McoFree(dbg_new_sizes); dbg_new_sizes = 0L; if (dbg_new_counts) McoFree(dbg_new_counts); dbg_new_counts = 0L; if (dbg_new_levels) McoFree(dbg_new_levels); dbg_new_levels = 0L; if (dbg_hand_ptrs) McoFree(dbg_hand_ptrs); dbg_hand_ptrs = 0L; if (dbg_hand_sizes) McoFree(dbg_hand_sizes); dbg_hand_sizes = 0L; if (dbg_hand_counts) McoFree(dbg_hand_counts); dbg_hand_counts = 0L; if (dbg_hand_levels) McoFree(dbg_hand_levels); dbg_hand_levels = 0L; if (dbg_ptr_ptrs) McoFree(dbg_ptr_ptrs); dbg_ptr_ptrs = 0L; if (dbg_ptr_sizes) McoFree(dbg_ptr_sizes); dbg_ptr_sizes = 0L; if (dbg_ptr_counts) McoFree(dbg_ptr_counts); dbg_ptr_counts = 0L; if (dbg_ptr_levels) McoFree(dbg_ptr_levels); dbg_ptr_levels = 0L; }
McoStatus ScanCal::_globalcal(Matrix &mat, long num, double *mea, double *ref) { McoStatus status; long i, j; double white[3]; Matrix matdata(num, 3); double *rgbref; white[0] = 96.42; white[1] = 100.0; white[2] = 82.49; rgbref = (double*)McoMalloc(sizeof(double)*num*3); if(!rgbref) return MCO_MEM_ALLOC_ERROR; for(i = 0; i < num*3; i++) rgbref[i] = ref[i]; //convert lab to XYZ labtonxyzinplace(rgbref, num); nxyztoxyzinplace(rgbref, white, num); //convert XYZ to rgb matdata.loadstruct(rgbref); matdata.T(); Matrix matrefrgb = mat*matdata; matrefrgb.T(); matrefrgb.savestruct(rgbref); //build linearization double x[LINEAR_NUM], y[LINEAR_NUM]; long start = num - 23; long end = num; _linear = new PWlinear*[3]; for(j = 0; j < 3; j++){ for(i = start; i < end; i++){ y[i-start] = rgbref[i*3 + j]; x[i-start] = mea[i*3 + j]; } _linear[j] = new PWlinear(LINEAR_NUM, x, y); } //linearization stretch status = _linearstrech(3, _linear, num, mea); if(status != MCO_SUCCESS) return status; //create matrix for(i = 0; i < num*3; i++) rgbref[i] = ref[i]; //convert lab to xyz labtonxyzinplace(rgbref, num); nxyztoxyzinplace(rgbref, white, num); _gcal = new MultiLcal(3, 3, 3, func3); status = _gcal->compute(num, mea, rgbref); if(status != MCO_SUCCESS) { delete _gcal; return status; } McoFree(rgbref); return MCO_SUCCESS; }
McoStatus Matrix::_ludcmp(void) { int32 i, j, k; int32 imax; // row number with largest pivot double aamax, sum, dum; double *vv; //for save the scaling vv = (double*)McoMalloc(sizeof(double)*_row); if(!vv) return MCO_MEM_ALLOC_ERROR; for(i = 0; i < _row; i++) _indx[i] = i; _d = 1; for(i = 0; i < _row; i++){ aamax = 0.0; for( j = 0; j < _col; j++) if(fabs(_m[i][j]) > aamax) aamax = fabs(_m[i][j]); if( aamax == 0.0){ McoFree((void *) vv); return MCO_SINGULAR; } vv[i] = 1.0/aamax; } //loop over columns for( j = 0; j < _col; j++){ for( i = 0; i < j; i++) { sum = _m[i][j]; for( k = 0; k < i; k++) sum -= _m[i][k]*_m[k][j]; _m[i][j] = sum; } //search for largest pivot element aamax = 0; imax = j; for( i = j; i < _col; i++){ sum = _m[i][j]; for( k = 0; k < j; k++) sum -= _m[i][k]*_m[k][j]; _m[i][j] = sum; dum = vv[i]*fabs(sum); //for testing pivot if( dum > aamax){ imax = i; aamax = dum; } } if( j != imax) { //need interchange rows? j = i for( k = 0; k < _col; k++){ //interchange rows and change parity dum = _m[imax][k]; _m[imax][k] = _m[j][k]; _m[j][k] = dum; _d = -_d; //interchange scale factor dum = vv[imax]; vv[imax] = vv[j]; } //save the interchange information _indx[j] = imax; } //divide by the pivot element if( j != _col){ if( _m[j][j] == 0.0){ //pivot value is 0, singular matrix McoFree((void *) vv); return MCO_SINGULAR;//at least to the precision of the algorithm } dum = 1.0/ _m[j][j]; for(i = j+1; i < _row; i++) _m[i][j] *= dum; } } McoFree((void *) vv); if( _m[_row-1][_col-1] == 0.0) return MCO_SINGULAR; return MCO_SUCCESS; }
//matrix inverse ( only matrix with _row == _col can be inversed //if the matrix is singular, 0 matrix will be given //mathod to use in matrix operation is singular value decomposition Matrix& Matrix::inv(void) { McoStatus status; int32 i, j, k; double **max; //if not a square matrix, return singular error if( _row != _col){ _set_status(MCO_SINGULAR); return *this; } status = _ludcmp(); if(status != MCO_SUCCESS){ //singular matrix, everything assigned to 0 for(i = 0; i < _row; i++) for(j = 0; j < _col; j++) _m[i][j] = 0.0; _set_status(MCO_SINGULAR); } else{ max = (double**)McoMalloc(sizeof(double*)*_row); if(!max){ _set_status(MCO_MEM_ALLOC_ERROR); return *this; } for( j = 0; j < _row; j++){ max[j] = (double*)McoMalloc(sizeof(double)*_col); if(!max[j]){ _set_status(MCO_MEM_ALLOC_ERROR); for(k = j-1; k >= 0; k--) McoFree((void *) max[k]); McoFree((void *) max); return *this; } } //set to a I matrix and solve the inverse for( i = 0; i < _row; i++){ for( j = 0; j < _col; j++) max[i][j] = 0.0; max[i][i] = 1.0; _lubksb(max[i]); } //fix on 8/12 //note!!, because the max contains the transverse of //of the inverse, do transverse and get it back double tempval; for( i = 0; i < _row; i++){ for( j = i; j < _col; j++){ tempval = max[i][j]; max[i][j] = max[j][i]; max[j][i] = tempval; } } //end of fix for( i = 0; i < _row; i++) McoFree((void *) _m[i]); McoFree((void *) _m); _m = max; } return *this; }