예제 #1
0
void reconstruct_laplacian_pyramid(uint32_t nlev, uint32_t npixels, double *tmp_fullsize, double *tmp2_fullsize, double *tmp_halfsize, double ***pyr, uint32_t *pyr_r, uint32_t *pyr_c, uint32_t r, uint32_t c, double *dst){

    for(int k = 0; k < CHANNELS; k++){
        double **pyrk = pyr[k];

        // reconstruct image for channel k
        if (nlev-2 >= 0){
            int v = nlev-2;
            upsample(pyrk[v+1],pyr_r[v+1],pyr_c[v+1],pyr_r[v],pyr_c[v],tmp_halfsize,tmp2_fullsize);
            for(int i = 0; i < pyr_r[v]*pyr_c[v]; i++){
                tmp_fullsize[i] = pyrk[v][i] + tmp2_fullsize[i]; COST_INC_ADD(1);
            }
        }
        for (int v = nlev-3; v >= 0; v--){
            upsample(tmp_fullsize,pyr_r[v+1],pyr_c[v+1],pyr_r[v],pyr_c[v],tmp_halfsize,tmp2_fullsize);
            for(int i = 0; i < pyr_r[v]*pyr_c[v]; i++){
                tmp_fullsize[i] = pyrk[v][i] + tmp2_fullsize[i]; COST_INC_ADD(1);
            }
        }

        //store into result image
        //TODO SIMD nocache
        for(int i = 0; i < npixels; i++){
            dst[i*CHANNELS+k] = tmp_fullsize[i];
        }
    }
}
예제 #2
0
unsigned char *
get_argb_422 (JpegDecoder *dec)
{
  uint32_t *tmp;
  uint8_t *tmp_u;
  uint8_t *tmp_v;
  uint32_t *argb_image;
  uint8_t *yp, *up, *vp;
  uint32_t *argbp;
  int j;

  tmp = malloc (4 * dec->width * dec->height);
  tmp_u = malloc (dec->width);
  tmp_v = malloc (dec->width);
  argb_image = malloc (4 * dec->width * dec->height);

  yp = dec->components[0].image;
  up = dec->components[1].image;
  vp = dec->components[2].image;
  argbp = argb_image;
  for(j=0;j<dec->height;j++){
    upsample (tmp_u, up, dec->width);
    upsample (tmp_v, vp, dec->width);
    yuv_mux (tmp, yp, tmp_u, tmp_v, dec->width);
    oil_colorspace_argb(argbp, tmp, jfif_matrix, dec->width);
    yp += dec->components[0].rowstride;
    up += dec->components[1].rowstride;
    vp += dec->components[2].rowstride;
    argbp += dec->width;
  }
  free(tmp);
  free(tmp_u);
  free(tmp_v);
  return (unsigned char *)argb_image;
}
예제 #3
0
TEST(RealVectorMethods, Upsample) {
	double inputData[] = { 1, 10001, 8, -5, 6, 2, 9, 1 };
	double expectedData[] = { 1, 0, 0, 10001, 0, 0, 8, 0, 0, -5, 0, 0, 6, 0, 0, 2, 0, 0, 9, 0, 0, 1, 0, 0 };
	double expectedData2[] = { 0, 1, 0, 0, 10001, 0, 0, 8, 0, 0, -5, 0, 0, 6, 0, 0, 2, 0, 0, 9, 0, 0, 1, 0 };
	double expectedData3[] = { 0, 0, 0, 1, 0, 0, 0, 10001, 0, 0, 0, 8, 0, 0, 0, -5, 0, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0, 9, 0, 0, 0, 1 };
	unsigned numElements = sizeof(inputData) / sizeof(inputData[0]);
	NimbleDSP::RealVector<double> bufSave(inputData, numElements);
	NimbleDSP::RealVector<double> buf(0);

	buf = bufSave;
	upsample(buf, 3);
	for (unsigned i = 0; i<numElements; i++) {
		EXPECT_EQ(expectedData[i], buf[i]);
	}

	buf = bufSave;
	upsample(buf, 3, 1);
	for (unsigned i = 0; i<numElements; i++) {
		EXPECT_EQ(expectedData2[i], buf[i]);
	}

	buf = bufSave;
	upsample(buf, 4, 3);
	for (unsigned i = 0; i<numElements; i++) {
		EXPECT_EQ(expectedData3[i], buf[i]);
	}
}
예제 #4
0
unsigned char *
get_argb_420 (JpegDecoder *dec)
{
  uint32_t *tmp;
  uint8_t *tmp_u;
  uint8_t *tmp_v;
  uint8_t *tmp1;
  uint32_t *argb_image;
  uint8_t *yp, *up, *vp;
  uint32_t *argbp;
  int j;
  int halfwidth;
  int halfheight;

  halfwidth = (dec->width + 1)>>1;
  tmp = malloc (4 * dec->width * dec->height);
  tmp_u = malloc (dec->width);
  tmp_v = malloc (dec->width);
  tmp1 = malloc (halfwidth);
  argb_image = malloc (4 * dec->width * dec->height);

  yp = dec->components[0].image;
  up = dec->components[1].image;
  vp = dec->components[2].image;
  argbp = argb_image;
  halfheight = (dec->height+1)>>1;
  for(j=0;j<dec->height;j++){
    uint32_t weight = 192 - 128*(j&1);

    oil_merge_linear_u8(tmp1,
        up + dec->components[1].rowstride * CLAMP((j-1)/2,0,halfheight-1),
        up + dec->components[1].rowstride * CLAMP((j+1)/2,0,halfheight-1),
        &weight, halfwidth);
    upsample (tmp_u, tmp1, dec->width);
    oil_merge_linear_u8(tmp1,
        vp + dec->components[2].rowstride * CLAMP((j-1)/2,0,halfheight-1),
        vp + dec->components[2].rowstride * CLAMP((j+1)/2,0,halfheight-1),
        &weight, halfwidth);
    upsample (tmp_v, tmp1, dec->width);

    yuv_mux (tmp, yp, tmp_u, tmp_v, dec->width);
    oil_colorspace_argb(argbp, tmp, jfif_matrix, dec->width);
    yp += dec->components[0].rowstride;
    argbp += dec->width;
  }
  free(tmp);
  free(tmp_u);
  free(tmp_v);
  free(tmp1);
  return (unsigned char *)argb_image;
}
예제 #5
0
void reconstruct_laplacian_pyramid(uint32_t channels, uint32_t nlev, double *tmp_fullsize, double *tmp2_fullsize, double *tmp_halfsize, double **pyr, uint32_t *pyr_r, uint32_t *pyr_c, uint32_t r, uint32_t c, double *dst){
    if (nlev-2 >= 0){
        int v = nlev-2;
        upsample(pyr[v+1],pyr_r[v+1],pyr_c[v+1],channels,pyr_r[v],pyr_c[v],tmp_halfsize,tmp2_fullsize);
        for(int i = 0; i < pyr_r[v]*pyr_c[v]*channels; i++){
            dst[i] = pyr[v][i] + tmp2_fullsize[i]; COST_INC_ADD(1);
        }
    }
    for (int v = nlev-3; v >= 0; v--){
        upsample(dst,pyr_r[v+1],pyr_c[v+1],channels,pyr_r[v],pyr_c[v],tmp_halfsize,tmp2_fullsize);
        for(int i = 0; i < pyr_r[v]*pyr_c[v]*channels; i++){
            dst[i] = pyr[v][i] + tmp2_fullsize[i]; COST_INC_ADD(1);
        }
    }
}
예제 #6
0
static inline double distort(EXCITER *p, double in)
{
    double samples[2], ans;
    int i;
    double ap = p->ap, an = p->an, kpa = p->kpa, kna = p->kna,
          kpb = p->kpb, knb = p->knb, pwrq = p->pwrq;
    //printf("in: %f\n", in);
    upsample(p, samples, in);
    for (i = 0; i < p->over; i++) {
      double proc = samples[i];
      double med;
      //printf("%d: %f-> ", i, proc);
      if (proc >= 0.0) {
        med = (D(ap + proc * (kpa - proc)) + kpb) * pwrq;
      } else {
        med = - (D(an - proc * (kna + proc)) + knb) * pwrq;
      }
      proc = p->srct * (med - p->prev_med + p->prev_out);
      //printf("%f\n", proc);
      p->prev_med = M(med);
      p->prev_out = M(proc);
      samples[i] = proc;
    }
    ans = downsample(p, samples);
    //printf("out: %f\n", ans);
    return ans;
}
예제 #7
0
void laplacian_pyramid(double *im, uint32_t r, uint32_t c, uint32_t nlev, double *tmp_halfsize, double *tmp_quartsize, double *tmp2_quartsize, double **pyr, uint32_t *pyr_r, uint32_t *pyr_c){
    uint32_t S_r = r;
    uint32_t S_c = c;
    uint32_t T_r = r;
    uint32_t T_c = c;

    double *tmp = NULL;

    if(0 < nlev-1){
        int v = 0;
        S_r = pyr_r[v+1];
        S_c = pyr_c[v+1];
        downsample(im,T_r,T_c,tmp_halfsize,S_r,S_c,tmp2_quartsize);
        upsample(tmp2_quartsize,S_r,S_c,pyr_r[v],pyr_c[v],tmp_halfsize,pyr[v]);
        for(int i = 0; i < T_r*T_c*3; i++){
            pyr[v][i] = im[i] - pyr[v][i]; COST_INC_ADD(1);
            COST_INC_LOAD(2);
            COST_INC_STORE(1);
        }
        T_r = S_r;
        T_c = S_c;
        double *tmp = tmp_quartsize;
        tmp_quartsize = tmp2_quartsize;
        tmp2_quartsize = tmp;
    }
    for(int v = 1; v < nlev-1; v++){
        S_r = pyr_r[v+1];
        S_c = pyr_c[v+1];
        downsample(tmp_quartsize,T_r,T_c,tmp_halfsize,S_r,S_c,tmp2_quartsize);
        upsample(tmp2_quartsize,S_r,S_c,pyr_r[v],pyr_c[v],tmp_halfsize,pyr[v]);
        for(int i = 0; i < T_r*T_c*3; i++){
            pyr[v][i] = tmp_quartsize[i] - pyr[v][i]; COST_INC_ADD(1);
            COST_INC_LOAD(2);
            COST_INC_STORE(1);
        }
        T_r = S_r;
        T_c = S_c;
        tmp = tmp_quartsize;
        tmp_quartsize = tmp2_quartsize;
        tmp2_quartsize = tmp;
    }
    memcpy(&(pyr[nlev-1][0]),&(tmp_quartsize[0]),T_r*T_c*3*sizeof(double));
    COST_INC_LOAD(T_r*T_c*3);
    COST_INC_STORE(T_r*T_c*3);
}
예제 #8
0
/*
count the number of nodal domains in grid
precondition: grid must be ny x nx

inputs:
        grid     - function values sampled at grid points
	counted  - array to store nodal domain numbers in. mask should be applied to this already
        nx       - number of samples in x-direction for grid
        ny       - number of samples in y-direction for grid
        k        - wavenumber of eigenfunction being interpolated
        dx       - sampled resoultion of eigenfunction
        M        - highest order bessel function to do
        upsample - upsampling ratio for interpolation
        sizefile - file to write sizes of domains to
output: return value - count of nodal domains
*/
int countNodalDomainsInterp(double **grid, bit_array_t *counted, int ny, int nx, double alpha, int M, int upsample_ratio, interp_stats *stats, FILE *sizefile) {
  int nodal_domain_count;
  bit_array_t *upsampled_grid;
  
  upsampled_grid = upsample(grid, ny, nx, alpha, M, upsample_ratio, stats);
  nodal_domain_count = countNodalDomains(upsampled_grid, counted, sizefile);
  free_bit_array(upsampled_grid);
  return nodal_domain_count;
}
예제 #9
0
void laplacian_pyramid(double *im, uint32_t r, uint32_t c, uint32_t channels, uint32_t nlev, double *tmp_halfsize, double *tmp_quartsize, double *tmp2_quartsize, double **pyr, uint32_t *pyr_r, uint32_t *pyr_c){
    uint32_t S_r = r;
    uint32_t S_c = c;
    uint32_t T_r = r;
    uint32_t T_c = c;

    double *tmp = NULL;

    if(0 < nlev-1){
        int v = 0;
        S_r = pyr_r[v+1];
        S_c = pyr_c[v+1];
        downsample(im,T_r,T_c,channels,tmp_halfsize,S_r,S_c,tmp2_quartsize);
        upsample(tmp2_quartsize,S_r,S_c,channels,pyr_r[v],pyr_c[v],tmp_halfsize,pyr[v]);
        for(int i = 0; i < T_r*T_c*channels; i++){
            pyr[v][i] = im[i] - pyr[v][i]; COST_INC_ADD(1);
        }
        T_r = S_r;
        T_c = S_c;
        double *tmp = tmp_quartsize;
        tmp_quartsize = tmp2_quartsize;
        tmp2_quartsize = tmp;
    }
    for(int v = 1; v < nlev-1; v++){
        S_r = pyr_r[v+1];
        S_c = pyr_c[v+1];
        downsample(tmp_quartsize,T_r,T_c,channels,tmp_halfsize,S_r,S_c,tmp2_quartsize);
        upsample(tmp2_quartsize,S_r,S_c,channels,pyr_r[v],pyr_c[v],tmp_halfsize,pyr[v]);
        for(int i = 0; i < T_r*T_c*channels; i++){
            pyr[v][i] = tmp_quartsize[i] - pyr[v][i]; COST_INC_ADD(1);
        }
        T_r = S_r;
        T_c = S_c;
        tmp = tmp_quartsize;
        tmp_quartsize = tmp2_quartsize;
        tmp2_quartsize = tmp;
    }
    //memcpy(dst,src,src_len*sizeof(double));
    for(int i = 0; i < T_r*T_c*channels; i++){
        pyr[nlev-1][i] = tmp_quartsize[i];
    }
}
예제 #10
0
파일: upsample.cpp 프로젝트: NVIDIA/Forma
int main(int argc, char** argv)
{
  float (*input)[N] = (float (*)[N])new float[M*N];
  float (*output)[2*N] = (float (*)[2*N])new float[2*M*2*N];
  float (*output_ref)[2*N] = (float (*)[2*N])new float[2*M*2*N];

  for( int i = 0 ; i < M ; i++ )
    for( int j = 0 ; j < N ; j++ )
      input[i][j] = (float)(rand()) / (float)(RAND_MAX-1);
      
  for( int i = 0 ; i < 2*M ; i++ ) 
    for( int j = 0 ; j < 2*N ; j++ ){
      output[i][j] = 0.0;
      output_ref[i][j] = 0.0;
    }

  upsample((float*)input,M,N,(float*)output);
  ref_output(input,output_ref);
  
  printf("Input :\n");
  for( int i = 0 ; i < M ; i++ ){
    for( int j = 0 ; j < N ; j++ )
      printf(" %f",input[i][j]);
    printf("\n");
  }
  printf("Output[%d,%d] :\n",2*M,2*N);
  for( int i = 0 ; i < 2*M ; i++ ){
    for( int j = 0 ; j < 2*N ; j++ )
      printf(" %f",output[i][j]);
    printf("\n");
  }
  printf("OutputRef[%d,%d] :\n",2*M,2*N);
  for( int i = 0 ; i < 2*M ; i++ ){
    for( int j = 0 ; j < 2*N ; j++ )
      printf(" %f",output_ref[i][j]);
    printf("\n");
  }
  double diff = 0.0;
  for( int i = 0 ; i < 2*M ; i++ )
    for( int j = 0 ; j < 2*N ; j++ ){
      if( output_ref[i][j] != output[i][j] )
	printf(" Diff at (%d,%d) : %f %f\n",i,j,output_ref[i][j],output[i][j]);
      diff += fabs(output_ref[i][j] - output[i][j]);
    }
  printf("Diff : %e\n",diff);
  if( diff > 1e-5 ){
    printf("Incorrect result\n");
    exit(1);
  }
  delete[] input;
  delete[] output;
  delete[] output_ref;
  return 0;
}
예제 #11
0
파일: cnn.cpp 프로젝트: GingerHugo/libdnn
void SubSamplingLayer::feedBackward(
    vector<mat>& errors, const vector<mat>& deltas) {

  // Since nInputs == nOutputs for subsampling layer, I just use N.
  size_t N = deltas.size();

  if (errors.size() != N)
    errors.resize(N);

  for (size_t i=0; i<N; ++i)
    errors[i] = upsample(deltas[i], _input_img_size, this->get_output_img_size()) / (_scale * _scale);
}
예제 #12
0
int main(int argc, char *argv[])
{
  static char *Spec[] = {"<input:string> -o <string> -tile_number <int> [-upsample <string>]", NULL};
  Process_Arguments(argc, argv, Spec, 1);

  char filepath[500];
  int i;
  int n = Get_Int_Arg("-tile_number");
  for (i = 0; i < n; i++) {
    sprintf(filepath, "%s/%03d", Get_String_Arg("input"), i+1);
    int n = dir_fnum(filepath, "tif");
    sprintf(filepath, "%s/%03d.xml", Get_String_Arg("-o"), i+1);
    FILE *fp = GUARDED_FOPEN(filepath, "w");
    fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
    fprintf(fp, "<trace>\n");
    fprintf(fp, "<data>\n");
    fprintf(fp, "<image type=\"bundle\">\n");
    fprintf(fp, "<prefix>%s/%03d/</prefix>\n", Get_String_Arg("input"), i+1);
    fprintf(fp, "<suffix>.tif</suffix>\n");
    if (n > 100) {
      fprintf(fp, "<num_width>3</num_width>\n");
    } else {
      fprintf(fp, "<num_width>2</num_width>\n");
    }
    fprintf(fp, "<first_num>1</first_num>\n");
    fprintf(fp, "</image>\n");
    fprintf(fp, "<resolution><x>0.0375</x><y>0.0375</y><z>0.2</z></resolution>\n");
    fprintf(fp, "</data>\n");
    fprintf(fp, "</trace>\n");
    fclose(fp);
    printf("%s created\n", filepath);
  }

  if (Is_Arg_Matched("-upsample")) {
    if (fexist(Get_String_Arg("-upsample"))) {
      FILE *fp = fopen(Get_String_Arg("-upsample"), "r");
      String_Workspace *sw = New_String_Workspace();
      char *line = NULL;
      int n;
      line = Read_Line(fp, sw);
      int *array = String_To_Integer_Array(line, NULL, &n);
      int i;
      for (i = 0; i < n; i++) {
	upsample(Get_String_Arg("-o"), array[i]);
      }
      fclose(fp);
    }
  }

  return 0;
}
void AdaptiveManifoldFilterN::buildManifoldsAndPerformFiltering(vector<Mat>& eta, Mat1b& cluster, int treeLevel)
{
    CV_DbgAssert((int)eta.size() == jointCnNum);

    //splatting
    Size etaSize = eta[0].size();
    CV_DbgAssert(etaSize == srcSize || etaSize == smallSize);

    if (etaSize == srcSize)
    {
        compute_w_k(eta, w_k, sigma_r_over_sqrt_2, treeLevel);
        etaFull = eta;
        downsample(eta, eta);
    }
    else
    {
        upsample(eta, etaFull);
        compute_w_k(etaFull, w_k, sigma_r_over_sqrt_2, treeLevel);
    }
    
    //blurring
    Psi_splat_small.resize(srcCnNum);
    for (int si = 0; si < srcCnNum; si++)
    {
        Mat tmp;
        multiply(srcCn[si], w_k, tmp);
        downsample(tmp, Psi_splat_small[si]);
    }
    downsample(w_k, Psi_splat_0_small);

    vector<Mat>& Psi_splat_small_blur = Psi_splat_small;
    Mat& Psi_splat_0_small_blur = Psi_splat_0_small;

    float rf_ss = (float)(sigma_s_ / getResizeRatio());
    float rf_sr = (float)(sigma_r_over_sqrt_2);
    RFFilterPass(eta, Psi_splat_small, Psi_splat_0_small, Psi_splat_small_blur, Psi_splat_0_small_blur, rf_ss, rf_sr);

    //slicing
    {
        Mat tmp;
        for (int i = 0; i < srcCnNum; i++)
        {
            upsample(Psi_splat_small_blur[i], tmp);
            multiply(tmp, w_k, tmp);
            add(sum_w_ki_Psi_blur_[i], tmp, sum_w_ki_Psi_blur_[i]);
        }
        upsample(Psi_splat_0_small_blur, tmp);
        multiply(tmp, w_k, tmp);
        add(sum_w_ki_Psi_blur_0_, tmp, sum_w_ki_Psi_blur_0_);
    }

    //build new manifolds
    if (treeLevel < curTreeHeight)
    {
        Mat1b cluster_minus, cluster_plus;

        computeClusters(cluster, cluster_minus, cluster_plus);

        vector<Mat> eta_minus(jointCnNum), eta_plus(jointCnNum);
        {
            Mat1f teta = 1.0 - w_k;
            computeEta(teta, cluster_minus, eta_minus);
            computeEta(teta, cluster_plus, eta_plus);
        }

        //free memory to continue deep recursion
        eta.clear();
        cluster.release();

        buildManifoldsAndPerformFiltering(eta_minus, cluster_minus, treeLevel + 1);
        buildManifoldsAndPerformFiltering(eta_plus, cluster_plus, treeLevel + 1);
    }
}
Array1D<T> lininterp(const Array1D<T>& v, int usf)
{
  Array1D<T> u;
  upsample(v,usf,u);
  return u;  
}
예제 #15
0
파일: decode.c 프로젝트: daic0r/icejpeg
int process_segment(void)
{
    word marker;
    int err;
    
    marker = fetch_word();
    if (marker == 0xFFD9)
    {
		iceenv.eoi = 1;
#ifdef _JPEG_DEBUG
        printf("EOI detected! Done.\n");
#endif
        return ERR_OK;
    }
    
    iceenv.cur_segment_len = fetch_word();
    
    switch (marker)
    {
        case 0xFFE0:
            err = process_app0();
            break;
        case 0xFFDB:
            err = process_dqt();
            break;
        case 0xFFC0:
            err = process_sof0();
            break;
        case 0xFFC4:
            err = process_dht();
            break;
        case 0xFFDD:
            err = process_dri();
            break;
        case 0xFFDA:
            err = gen_huffman_tables();
            err = process_sos();
            err = decode_scan();
            err = upsample();
            err = create_image();
            break;
		case 0xFFC1:
		case 0xFFC2:
		case 0xFFC3:
		case 0xFFC5:
		case 0xFFC6:
		case 0xFFC7:
		case 0xFFC9:
		case 0xFFCA:
		case 0xFFCB:
		case 0xFFCD:
		case 0xFFCE:
		case 0xFFCF:
			err = ERR_NOT_BASELINE;
			break;
		default:
#ifdef _JPEG_DEBUG
            printf("Skipping unknown segment %X\n", marker & 0xFF);
#endif
            iceenv.buf_pos += iceenv.cur_segment_len - 2;
            err = ERR_OK;
            break;
    }
    
    return err;
}
예제 #16
0
파일: noiseTest.c 프로젝트: spinos/fungi
void initTextures()
{
	glGenTextures(1, &texname);	
	glBindTexture(GL_TEXTURE_2D, texname);	
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

	float *texels = malloc(WIDTH*HEIGHT*sizeof(float));
	int u, v;
	
		for(v=0; v<HEIGHT; v++) {
			for(u=0; u<WIDTH; u++) {
				texels[v*WIDTH+u] = (float)(random()%1931)/1931.f;
				texels[v*WIDTH+u] = sin(3.14*(float)(u+0.5)/128.f*16.f)*0.5+0.5;
				//texels[v*WIDTH+u] *= sin(3.14*(float)v/128.f*6.f+3.14)*0.5+0.5;
				//texels[v*WIDTH+u] = 0;
			}
		}
		
		for(v=50; v<78; v++) 
			for(u=50; u<78; u++) texels[v*WIDTH+u] = 1;
	readEXRRED("/Users/jianzhang/Pictures/tomcat.exr", WIDTH, HEIGHT, texels);
	
	glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE32F_ARB, WIDTH, HEIGHT, 0, GL_LUMINANCE, GL_FLOAT, texels);
	


float *dns = malloc(DNWIDTH*DNHEIGHT*sizeof(float));
	
		for(v=0; v<DNHEIGHT; v++) {
			for(u=0; u<DNWIDTH; u++) {
				dns[v*DNWIDTH+u] = downsample(u, v, texels);
			}
		}
		
			glGenTextures(1, &dnname);	
	glBindTexture(GL_TEXTURE_2D, dnname);	
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	
	glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE32F_ARB, DNWIDTH, DNHEIGHT, 0, GL_LUMINANCE, GL_FLOAT, dns);
	
		float *ups = malloc(WIDTH*HEIGHT*sizeof(float));

		for(v=0; v<HEIGHT; v++) {
			for(u=0; u<WIDTH; u++) {
				ups[v*WIDTH+u] = upsample(u, v, dns);
			}
		}
		
		glGenTextures(1, &upname);	
	glBindTexture(GL_TEXTURE_2D, upname);	
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	
	glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE32F_ARB, WIDTH, HEIGHT, 0, GL_LUMINANCE, GL_FLOAT, ups);
	
	float *fine = malloc(WIDTH*HEIGHT*sizeof(float));
	
	float *tmp = malloc(WIDTH*HEIGHT*sizeof(float));
	
		for(v=0; v<HEIGHT; v++) {
			for(u=0; u<WIDTH; u++) {
				fine[v*WIDTH+u] = texels[v*WIDTH+u] - ups[v*WIDTH+u];
				tmp[v*WIDTH+u] = fine[v*WIDTH+u];
			}
		}
		int offset = WIDTH/2 + 1;
		
		for(v=0; v<HEIGHT; v++) {
			for(u=0; u<WIDTH; u++) {
				fine[v*WIDTH+u] +=tmp[Modi(v+offset, HEIGHT)*WIDTH+Modi(u+offset, WIDTH)];
				fine[v*WIDTH+u] = 0.5 + fine[v*WIDTH+u]*0.5;
			}
		}
		
		glGenTextures(1, &fnname);	
	glBindTexture(GL_TEXTURE_2D, fnname);	
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	
	glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE32F_ARB, WIDTH, HEIGHT, 0, GL_LUMINANCE, GL_FLOAT, fine);
	
	COMPLEX *comimg = malloc(WIDTH*HEIGHT*sizeof(COMPLEX));
	
	
	for(v=0; v<HEIGHT; v++) {
			for(u=0; u<WIDTH; u++) {
				comimg[v*WIDTH+u].real = 0;
				comimg[v*WIDTH+u].imag = texels[v*WIDTH+u];
			}
		}
		
	FFT2D(comimg, WIDTH, HEIGHT, 1);
	
	for(v=0; v<HEIGHT; v++) {
			for(u=0; u<WIDTH; u++) {
				fine[Modi(v+64,HEIGHT)*WIDTH+Modi(u+64,WIDTH)] = 64*sqrt(comimg[v*WIDTH+u].real*comimg[v*WIDTH+u].real + comimg[v*WIDTH+u].imag * comimg[v*WIDTH+u].imag);
			}
		}
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE32F_ARB, WIDTH, HEIGHT, 0, GL_LUMINANCE, GL_FLOAT, fine);
	

	free(comimg);	
	free(ups);
	free(texels);
	free(dns);
	free(fine);
	
	glEnable(GL_TEXTURE_2D);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, texname);
	
	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, dnname);
	
	glUseProgram(program);
	glUniform1i(glGetUniformLocation(program, "WhiteNoise"), 0);
	glBindTexture(GL_TEXTURE_2D, texname);
	
	glGenTextures(1, &kerneltex);	
	glBindTexture(GL_TEXTURE_1D, kerneltex);	
	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	
glTexImage1D(GL_TEXTURE_1D, 0, GL_LUMINANCE32F_ARB, 32, 0, GL_LUMINANCE, GL_FLOAT, aCoeffs);

 //glEnable(GL_TEXTURE_1D);
	//glActiveTexture(GL_TEXTURE1);
	//glBindTexture(GL_TEXTURE_1D, kerneltex);
	
	glUniform1i(glGetUniformLocation(program, "FilterKernel"), 1);
}
예제 #17
0
파일: dsd_audio.c 프로젝트: KC9NJZ/dsd
void
processAudio (dsd_opts * opts, dsd_state * state)
{

  int i, n;
  float aout_abs, max, gainfactor, gaindelta, maxbuf;

  if (opts->audio_gain == (float) 0)
    {
      // detect max level
      max = 0;
      state->audio_out_temp_buf_p = state->audio_out_temp_buf;
      for (n = 0; n < 160; n++)
        {
          aout_abs = fabsf (*state->audio_out_temp_buf_p);
          if (aout_abs > max)
            {
              max = aout_abs;
            }
          state->audio_out_temp_buf_p++;
        }
      *state->aout_max_buf_p = max;
      state->aout_max_buf_p++;
      state->aout_max_buf_idx++;
      if (state->aout_max_buf_idx > 24)
        {
          state->aout_max_buf_idx = 0;
          state->aout_max_buf_p = state->aout_max_buf;
        }

      // lookup max history
      for (i = 0; i < 25; i++)
        {
          maxbuf = state->aout_max_buf[i];
          if (maxbuf > max)
            {
              max = maxbuf;
            }
        }

      // determine optimal gain level
      if (max > (float) 0)
        {
          gainfactor = ((float) 30000 / max);
        }
      else
        {
          gainfactor = (float) 50;
        }
      if (gainfactor < state->aout_gain)
        {
          state->aout_gain = gainfactor;
          gaindelta = (float) 0;
        }
      else
        {
          if (gainfactor > (float) 50)
            {
              gainfactor = (float) 50;
            }
          gaindelta = gainfactor - state->aout_gain;
          if (gaindelta > ((float) 0.05 * state->aout_gain))
            {
              gaindelta = ((float) 0.05 * state->aout_gain);
            }
        }
      gaindelta /= (float) 160;
    }
  else
    {
      gaindelta = (float) 0;
    }

  // adjust output gain
  state->audio_out_temp_buf_p = state->audio_out_temp_buf;
  for (n = 0; n < 160; n++)
    {
      *state->audio_out_temp_buf_p = (state->aout_gain + ((float) n * gaindelta)) * (*state->audio_out_temp_buf_p);
      state->audio_out_temp_buf_p++;
    }
  state->aout_gain += ((float) 160 * gaindelta);

  // copy audio datat to output buffer and upsample if necessary
  state->audio_out_temp_buf_p = state->audio_out_temp_buf;
  if (opts->split == 0)
    {
      for (n = 0; n < 160; n++)
        {
          upsample (state, *state->audio_out_temp_buf_p);
          state->audio_out_temp_buf_p++;
          state->audio_out_float_buf_p += 6;
          state->audio_out_idx += 6;
          state->audio_out_idx2 += 6;
        }
      state->audio_out_float_buf_p -= (960 + opts->playoffset);
      // copy to output (short) buffer
      for (n = 0; n < 960; n++)
        {
          if (*state->audio_out_float_buf_p > (float) 32760)
            {
              *state->audio_out_float_buf_p = (float) 32760;
            }
          else if (*state->audio_out_float_buf_p < (float) -32760)
            {
              *state->audio_out_float_buf_p = (float) -32760;
            }
          *state->audio_out_buf_p = (short) *state->audio_out_float_buf_p;
          state->audio_out_buf_p++;
          state->audio_out_float_buf_p++;
        }
      state->audio_out_float_buf_p += opts->playoffset;
    }
  else
    {
      for (n = 0; n < 160; n++)
        {
          if (*state->audio_out_temp_buf_p > (float) 32760)
            {
              *state->audio_out_temp_buf_p = (float) 32760;
            }
          else if (*state->audio_out_temp_buf_p < (float) -32760)
            {
              *state->audio_out_temp_buf_p = (float) -32760;
            }
          *state->audio_out_buf_p = (short) *state->audio_out_temp_buf_p;
          state->audio_out_buf_p++;
          state->audio_out_temp_buf_p++;
          state->audio_out_idx++;
          state->audio_out_idx2++;
        }
    }
}
예제 #18
0
파일: dpat.c 프로젝트: beku/Argyll-Releases
int
main(int argc,
	char *argv[]
) {
	double val[3], out[3], err;
	double ipat[DISIZE][DISIZE][3];
	double aerr, acount, xerr;
	int x, y;
	int i, j;
	int k, nn;

	printf("Hi there\n");

	rand32(time(NULL));

#ifdef TEST_POINT
	for (x = 0; x < DISIZE; x++) {
		for (y = 0; y < DISIZE; y++) {
			ipat[x][y][0] = 0.0;
			ipat[x][y][1] = 0.0;
			ipat[x][y][2] = 0.0;
		}
	}

	ipat[5][4][0] = 255.0;
	ipat[5][4][1] = 255.0;
	ipat[5][4][2] = 255.0;

	upsample(NULL, ipat);

#else

#ifdef NEVER

//	val[0] = 201.500000;
//	val[1] = 115.533403;
//	val[2] = 76.300000;

//	val[0] = 255.000000;
//	val[1] = 115.533403;
//	val[2] = 255.000000;

//	val[0] = 221.689875;
//	val[1] = 29.593255;
//	val[2] = 140.820878;

//	val[0] = 212.377797;
//	val[1] = 228.338903;
//	val[2] = 70.153296;

//	val[0] = 231.554511;
//	val[1] = 0.000000;
//	val[2] = 51.958048;

//	val[0] = 255.000000;
//	val[1] = 144.768052;
//	val[2] = 179.737212;

//	val[0] = 194.854956;
//	val[1] = 41.901887;
//	val[2] = 20.434793;

//	val[0] = 250.100121; 
//	val[1] = 83.484217;
//	val[2] = 42.867603;

//	val[0] = 255.000000;
//	val[1] = 255.000000;
//	val[2] = 228.534759;

	// 1.71 -> 1.58, rand 2.2
//	val[0] = 255.000000;
//	val[1] = 176.894769;
//	val[2] = 8.932806;

	// 1.54 -> 0.762592, rand 0.3 
//	val[0] = 216.873703;
//	val[1] = 250.908094;

	// 1.05
//	val[0] = 167.284458;
//	val[1] = 248.945210;
//	val[2] = 199.023452;

	// 1.07
//	val[0] = 211.045184;
//	val[1] = 27.825141;
//	val[2] = 63.883148;

	// 1.928
//	val[0] = 255.000000;
//	val[1] = 0.439284;
//	val[2] = 210.928135;

	// 1.278
//	val[0] = 218.693614;
//	val[1] = 222.890101;
//	val[2] = 174.779727;

	// 1.334501
//	val[0] = 253.931573;
//	val[1] = 230.278945;
//	val[2] = 185.677389;

//	printf("In RGB %f %f %f\n",val[0],val[1],val[2]);
//	ccast2YCbCr(NULL, out, val);
//	printf("YCbCr %f %f %f\n",out[0],out[1],out[2]);
//	YCbCr2ccast(NULL, out, out);
//	printf("RGB %f %f %f\n",out[0],out[1],out[2]);
	

	vv = 1;
	err = get_ccast_dith(ipat, val);

	printf("Got pat with err %f\n",err);

#else
	aerr = 0.0;
	acount = 0.0;
	xerr = 0.0;
	for (nn = 0; nn < 200000; nn++) {

		for (k = 0; k < 3; k++) {
			val[k] = d_rand(-5.0, 255.0 + 5.0);
			if (val[k] < 0.0)
				val[k] = 0.0;
			else if (val[k] > 255.0)
				val[k] = 255.0;
		}

		err = get_ccast_dith(ipat, val);

		if (err >= 1.5 || 
		 (  err >= 1.0
		 && val[0] != 0.0 && val[0] != 255.0
		 && val[1] != 0.0 && val[1] != 255.0
		 && val[2] != 0.0 && val[2] != 255.0)) {
			printf("Target RGB %f %f %f, err %f\n", val[0], val[1], val[2],err);
//			vv = 1;
//			comput_pat(ipat, val);
//			break;
		}

		aerr += err;
		acount++;
		if (err > xerr)
			xerr = err;
	}

	aerr /= acount;
	printf("After %d trials, aerr = %f, maxerr = %f\n",nn,aerr,xerr); 
#endif
#endif

	return 0;
}
예제 #19
0
파일: dpat.c 프로젝트: beku/Argyll-Releases
/* return the delta to the target */
double get_ccast_dith(double ipat[DISIZE][DISIZE][3], double val[3]) {
	double itpat[DISIZE][DISIZE][3], tpat[DISIZE][DISIZE][3];
	double irtpat[DISIZE][DISIZE][3], rtpat[DISIZE][DISIZE][3];	/* resulting for tpat */
	double berr = 0.0;
	int n, k;
	int x, y;
	int i, j;
	int ii;
	struct {
    	int x, y;
	} order[16] = {
// Dispersed:
	    { 3, 1 },{ 1, 3 },{ 1, 1 },{ 3, 0 },{ 3, 3 },{ 1, 2 },{ 3, 2 },{ 2, 0 },
		{ 1, 0 },{ 0, 3 },{ 0, 1 },{ 2, 1 },{ 2, 2 },{ 0, 0 },{ 0, 2 },{ 2, 3 }
// Clustered:
//	    { 0, 0 },{ 0, 1 },{ 1, 1 },{ 1, 0 },{ 2, 0 },{ 3, 0 },{ 3, 1 },{ 2, 1 },
//		{ 2, 2 },{ 3, 2 },{ 3, 3 },{ 2, 3 },{ 1, 3 },{ 1, 2 },{ 0, 2 },{ 0, 3 }
	};
	int cix = 0;
	int nsur = 8, ncomb = 4;
	double sur[8][3];			/* RGB surrounding values to use */
	double ressur[8][3];		/* resulting RGB surrounding values */
	int  bcc[8];				/* Best combination */
	double bw[8];				/* Best weight */
	int biw[8];					/* Best integer weight/16 */
	double dval[3];				/* Dithered value */
	double err[3], werr;
	double errxs;
	/* Tuning params */
	int nitters = 300;			/* No itters */
	int rand_count = 150;
	double rand_start = 4.5;	/* Ramp with itters */
	double rand_end = 0.2;
	double rand_pow = 1.5;
	double mxerrxs = 2.5;		/* accumulated error reset threshold */
	unsigned int randv = 0x1234;

	/* 32 bit pseudo random sequencer based on XOR feedback */
	/* generates number between 1 and 4294967295 */
#define PSRAND32F(S) (((S) & 0x80000000) ? (((S) << 1) ^ 0xa398655d) : ((S) << 1))

	/* Locate the 8 surrounding RGB verticies */
	for (n = 0; n < 8; n++) {
		for (k = 0; k < 3; k++) {
			if (n & (1 << k))
				sur[n][k] = ceil(val[k]);
			else
				sur[n][k] = floor(val[k]);
		}

//printf("Input sur %d: %f %f %f\n",n,sur[n][0], sur[n][1], sur[n][2], sur[n][3]);
		/* Figure out what RGB values to use to surround the point, */
		/* and what actual RGB values to expect from using them. */
		quant_rgb(n, ressur[n], sur[n]);
//printf("Quant sur %d: %f %f %f\n",n,sur[n][0], sur[n][1], sur[n][2], sur[n][3]);
//printf("   ressur %d: %f %f %f\n",n,ressur[n][0], ressur[n][1], ressur[n][2], ressur[n][3]);
//		printf("\n");
	}

	/* Reduce this to unique surrounders */
	for (nsur = 0, i = 0; i < 8; i++) {

		/* Check if the i'th entry is already in the list */
		for (j = 0; j < nsur; j++) {
			for (k = 0; k < 3; k++) {
				if (ressur[i][k] != ressur[j][k])
					break;
			}
			if (k < 3)
				continue;	/* Unique */
			break;			/* Duplicate */
		}
		if (j < nsur)		/* Duplicate */
			continue;
		
		/* Copy i'th to nsur */
		for (k = 0; k < 3; k++) {
			sur[nsur][k]    = sur[i][k];
			ressur[nsur][k] = ressur[i][k];
		}
		nsur++;
	}

#ifdef DIAGNOSTICS
	if (vv) {
		printf("There are %d unique surrounders:\n",nsur);
		for (n = 0; n < nsur; n++) {
			printf("sur %f %f %f\n",ressur[n][0], ressur[n][1], ressur[n][2]);
		}
	}
#endif

	/* Use an optimzer to set the initial values using all the unique */
	/* surrounders. */
	{
		double s[8]; 
		optcntx cntx;

		ncomb = nsur;
		for (n = 0; n < nsur; n++) {
			bcc[n] = n;
			bw[n] = 1.0/nsur;
			s[n] = 0.1;
		}

		cntx.di = nsur-1;
		cntx.val = val;
		cntx.ressur = &ressur;

		powell(NULL, cntx.di, bw, s, 1e-4, 1000, optfunc, &cntx, NULL, NULL); 

		/* Compute baricentric values */
		bw[nsur-1] = 0.0;
		for (n = 0; n < (nsur-1); n++) {
			if (bw[n] < 0.0)
				bw[n] = 0.0;
			else if (bw[n] > 1.0)
				bw[n] = 1.0;
			bw[nsur-1] += bw[n];
		}
		if (bw[nsur-1] > 1.0) {		/* They summed to over 1.0 */
			for (n = 0; n < (nsur-1); n++)
				bw[n] *= 1.0/bw[nsur-1];	/* Scale them down */
			bw[nsur-1] = 1.0;
		}
		bw[nsur-1] = 1.0 - bw[nsur-1];		/* Remainder */
	}

	/* Check the result */
#ifdef DIAGNOSTICS
	if (vv) {
		double tmp[3], err;

		/* Compute interpolated result */
		for (k = 0; k < 3; k++)
			tmp[k] = 0.0;
		for (n = 0; n < ncomb; n++) {
			for (k = 0; k < 3; k++)
				tmp[k] += bw[n] * ressur[bcc[n]][k];
		}
		/* Compute error */
		err = 0.0;
		for (k = 0; k < 3; k++) {
			tmp[k] -= val[k];
			err += tmp[k] * tmp[k];
		}
		err = sqrt(err);
		for (n = 0; n < ncomb; n++)
			printf("Comb %d weight %f rgb %f %f %f\n",bcc[n],bw[n],ressur[bcc[n]][0],ressur[bcc[n]][1],ressur[bcc[n]][2]);
		printf("Error %f %f %f rms %f\n",tmp[0], tmp[1], tmp[2], err);
		printf("\n");
	}
#endif

	/* Compute the number of pixels for each surounder value */
	{
		int sw[8], rem;

		/* Sort the weightings from smallest to largest */
		for (n = 0; n < 8; n++)
			sw[n] = n;

		for (i = 0; i < (ncomb-1); i++) {
			for (j = i+1; j < ncomb; j++) {
				if (bw[sw[j]] < bw[sw[i]]) {
					int tt = sw[i];		/* Swap them */
					sw[i] = sw[j];
					sw[j] = tt;
				} 
			}
		}

		/* Compute the nearest integer weighting out of 16 */
		rem = 16;
		for (i = 0; i < (ncomb-1) && rem > 0; i++) {
			n = sw[i];
			biw[n] = (int)(16.0 * bw[n] + 0.5);
			rem -= biw[n];
			if (rem <= 0)
				rem = 0;
		}
		for (; i < ncomb; i++) {
			n = sw[i];
			biw[n] = rem;
		}
#ifdef DIAGNOSTICS
		if (vv) {
			for (n = 0; n < ncomb; n++)
				printf("Comb %d iweight %i rgb %f %f %f\n",bcc[n],biw[n],ressur[bcc[n]][0],ressur[bcc[n]][1],ressur[bcc[n]][2]);
		}
#endif
	}

	/* Set the initial pattern according to the integer weighting */
	for (cix = 0, n = 0; n < ncomb; n++) {
		for (i = 0; i < biw[n]; i++) {
			x = order[cix].x;
			y = order[cix].y;
			cix++;
			for (k = 0; k < 3; k++) {
				tpat[x][y][k] = itpat[x][y][k]  = sur[bcc[n]][k];
				rtpat[x][y][k] = irtpat[x][y][k] = ressur[bcc[n]][k];
			}
		}
	}

#ifdef DIAGNOSTICS
	/* Check initial pattern error */
	if (vv) {
		printf("Input pat:\n");
		for (x = 0; x < DISIZE; x++) {
			for (y = 0; y < DISIZE; y++) {
				if (y > 0)
					printf(", ");
				printf("%3.0f %3.0f %3.0f",rtpat[x][y][0], rtpat[x][y][1], rtpat[x][y][2]);
			}
			printf("\n");
		}
	}
#endif

	upsample(dval, rtpat);

	werr = 0.0;
	for (k = 0; k < 3; k++) {
		err[k] = dval[k] - val[k]; 
		if (fabs(err[k]) > werr)
			werr = fabs(err[k]);
	}

#ifdef DIAGNOSTICS
	if (vv) {
		printf("Target %f %f %f -> %f %f %f\n", val[0], val[1], val[2], dval[0], dval[1], dval[2]);
		printf("Error %f %f %f werr %f\n", err[0], err[1], err[2], werr);
	}
#endif

	berr = werr;
	for (x = 0; x < DISIZE; x++) {
		for (y = 0; y < DISIZE; y++) {
			for (k = 0; k < 3; k++)
				ipat[x][y][k] = tpat[x][y][k];
		}
	}

	/* Improve fit if needed */
	/* This is a bit stocastic */
	errxs = 0.0;
	for (ii = 0; ii < nitters; ii++) {		/* Until we give up */
		double corr[3];		/* Correction direction needed */
		double bdot;
		int bx, by;

		double wycc, mm;
		double cell[3];		/* Cell being modified value */
		double ccell[3];	/* Corrected cell */
		double pcell[3];		/* Proposed new cell value */

		for (k = 0; k < 3; k++)
			corr[k] = val[k] - dval[k];
#ifdef DIAGNOSTICS
		if (vv)
			printf("corr needed %f %f %f\n", corr[0], corr[1], corr[2]);
#endif

		/* Scale it and limit it */
		for (k = 0; k < 3; k++) {
			double dd = 16.0 * corr[k];
			if (dd >= 1.0)
				dd = 1.0;
			else if (dd <= -1.0)
				dd = -1.0;
			else
				dd = 0.0;
			corr[k] = dd;
		}

		if (corr[0] == 0.0 && corr[1] == 0 && corr[2] == 0.0) {
#ifdef DIAGNOSTICS
			if (vv)
				printf("No correction possible - done\n");
#endif
			break;
		}
			
#ifdef DIAGNOSTICS
		if (vv)
			printf("scaled corr %f %f %f\n", corr[0], corr[1], corr[2]);
#endif

		/* Search dither cell and surrounder for a combination */
		/* that is closest to the change we want to make. */
		bdot = 1e6;
		bx = by = n = 0;
		for (x = 0; x < DISIZE; x++) {
			double rlevel = rand_start + (rand_end - rand_start)
			                * pow((ii % rand_count)/rand_count, rand_pow);

			for (y = 0; y < DISIZE; y++) {
				for (i = 0; i < ncomb; i++) {
					double dot = 0.0;
					for (k = 0; k < 3; k++)
						dot += (ressur[bcc[i]][k] - rtpat[x][y][k]) * corr[k];

					/* Ramp the randomness up */
//					dot += d_rand(0.0, 0.1 + (2.5-0.1) * ii/nitters);
//					dot += d_rand(-rlevel, rlevel);
					/* use a deterministic random element, so that */
					/* the dither patterns are repeatable. */
					randv = PSRAND32F(randv);
					dot += rlevel * 2.0 * ((randv - 1)/4294967294.0 - 0.5);

					if (dot <= 0.0)
						dot = 1e7;
					else {
						dot = (dot - 1.0) * (dot - 1.0);
					}
//printf("dot %f from sur %f %f %f to pat %f %f %f\n", dot, ressur[bcc[i]][0], ressur[bcc[i]][1], ressur[bcc[i]][2], rtpat[x][y][0], rtpat[x][y][1], rtpat[x][y][2]);

					if (dot < bdot) {
						bdot = dot;
						bx = x;
						by = y;
						n = i;
					}
				}
			}
		}

#ifdef DIAGNOSTICS
		if (vv) {
			printf("Changing cell [%d][%d] %f %f %f with dot %f\n",bx,by,rtpat[bx][by][0],rtpat[bx][by][1],rtpat[bx][by][2],bdot);
			printf("           to sur %d: %f %f %f\n",n, ressur[bcc[n]][0], ressur[bcc[n]][1], ressur[bcc[n]][2]);
		}
#endif

		/* Substitute the best correction for this cell */
		for (k = 0; k < 3; k++) {
			tpat[bx][by][k] = sur[bcc[n]][k];
			rtpat[bx][by][k] = ressur[bcc[n]][k];
		}

#ifdef DIAGNOSTICS
		if (vv) {
			printf("Input pat:\n");
			for (x = 0; x < DISIZE; x++) {
				for (y = 0; y < DISIZE; y++) {
					if (y > 0)
						printf(", ");
					printf("%3.0f %3.0f %3.0f",rtpat[x][y][0], rtpat[x][y][1], rtpat[x][y][2]);
				}
				printf("\n");
			}
		}
#endif

		upsample(dval, rtpat);
	
		werr = 0.0;
		for (k = 0; k < 3; k++) {
			err[k] = dval[k] - val[k]; 
			if (fabs(err[k]) > werr)
				werr = fabs(err[k]);
		}

		if (werr > berr) {
			errxs += werr - berr;
		}

		/* New best */
		if (werr < berr) {
			berr = werr;
			errxs = 0.0;
			for (x = 0; x < DISIZE; x++) {
				for (y = 0; y < DISIZE; y++) {
					for (k = 0; k < 3; k++) {
						ipat[x][y][k] = tpat[x][y][k];

						itpat[x][y][k] = tpat[x][y][k];
						irtpat[x][y][k] = rtpat[x][y][k];
					}
				}
			}
		}

#ifdef DIAGNOSTICS
		if (vv) {
			printf("Target %f %f %f -> %f %f %f\n", val[0], val[1], val[2], dval[0], dval[1], dval[2]);
			printf("Error %f %f %f werr %f\n", err[0], err[1], err[2], werr);
		}
#endif

		if (berr < 0.11) {
#ifdef DIAGNOSTICS
			if (vv)
				printf("best error %f < 0.11 - give up\n",berr);
#endif
			break;
		}

		/* If we're not making progress, reset to the last best */
		if (errxs > mxerrxs) {
#ifdef DIAGNOSTICS
			if (vv)
				printf("Restarting at ii %d \n",ii); 
#endif
			errxs = 0.0;
			for (x = 0; x < DISIZE; x++) {
				for (y = 0; y < DISIZE; y++) {
					for (k = 0; k < 3; k++) {
						tpat[x][y][k] = itpat[x][y][k];
						rtpat[x][y][k] = irtpat[x][y][k];
					}
				}
			}
		}
	}

#ifdef DIAGNOSTICS
	if (vv) {
		printf("Returning best error %f pat:\n",berr);
		for (y = 0; y < DISIZE; y++) {
			for (x = 0; x < DISIZE; x++) {
				if (x > 0)
					printf(",  ");
				printf("%3.0f %3.0f %3.0f",ipat[x][y][0], ipat[x][y][1], ipat[x][y][2]);
			}
			printf("\n");
		}
	}
#endif

	return berr;
}