/* * @brief Photographic tone-reproduction * * @param Y input luminance * @param L output tonemapped intensities * @param use_scales true: local version, false: global version of TMO * @param key maps log average luminance to this value (default: 0.18) * @param phi sharpening parameter (defaults to 1 - no sharpening) * @param num number of scales to use in computation (default: 8) * @param low size in pixels of smallest scale (should be kept at 1) * @param high size in pixels of largest scale (default 1.6^8 = 43) */ void tmo_reinhard02( unsigned int width, unsigned int height, const float *nY, float *nL, bool use_scales, float key, float phi, int num, int low, int high, bool temporal_coherent ) { const pfstmo::Array2D* Y = new pfstmo::Array2D(width, height, const_cast<float*>(nY)); pfstmo::Array2D* L = new pfstmo::Array2D(width, height, nL); int x,y; ::key = key; ::phi = phi; ::range = num; ::scale_low = low; ::scale_high = high; ::use_scales = (use_scales) ? 1 : 0; ::temporal_coherent = temporal_coherent; cvts.xmax = Y->getCols(); cvts.ymax = Y->getRows(); sigma_0 = log (scale_low); sigma_1 = log (scale_high); compute_bessel(); allocate_memory (); // reading image for( y=0 ; y<cvts.ymax ; y++ ) for( x=0 ; x<cvts.xmax ; x++ ) image[y][x][0] = (*Y)(x,y); copy_luminance(); scale_to_midtone(); if( use_scales ) { #ifdef APPROXIMATE build_pyramid(luminance, cvts.xmax, cvts.ymax); #else compute_fourier_convolution(); #endif } tonemap_image(); // saving image for( y=0 ; y<cvts.ymax ; y++ ) for( x=0 ; x<cvts.xmax ; x++ ) (*L)(x,y) = image[y][x][0]; // print_parameter_settings(); deallocate_memory(); clean_pyramid(); delete L; delete Y; }
Slic::Slic(const vector<unsigned char>& img, int rows_, int cols_, int chan_, int K_, int M_, int num_iters_, int max_levels, float scale_factor_) { #ifdef SLIC_DEBUG printf("Slic::constructor\n"); #endif // infer *actual* number of superpixels. float ar = float(cols_) / float(rows_); nx = sqrt(ar*float(K_)); ny = sqrt(float(K_) / ar); K = nx*ny; // figure out the size of each superpixel: float step_x = float(cols_) / float(nx + 1.0); float step_y = float(rows_) / float(ny + 1.0); if (scale_factor_ <= 1.0) { printf("Invalid scale factor (should be >1). Setting to 2.0\n"); scale_factor_ = 2.0; } scale_factor = scale_factor_; //------------------------------------------------------------------------- // figure out how many levels are needed. float mindim = (float)min(step_x, step_y); int k = 1; while (mindim > 4) { mindim /= scale_factor; k++; } if (k < max_levels) { printf("Only allowing %d levels\n", k); } num_levels = min(k, max_levels); rows = vector<int>(num_levels); cols = vector<int>(num_levels); search_region_x = vector<int>(num_levels); search_region_y = vector<int>(num_levels); rows[0] = rows_; cols[0] = cols_; search_region_x[0] = round(step_x*2.0); search_region_y[0] = round(step_y*2.0); for (int i = 1; i < num_levels; ++i) { rows[i] = rows[i - 1] / scale_factor; cols[i] = cols[i - 1] / scale_factor; search_region_x[i] = search_region_x[i - 1] / scale_factor; search_region_y[i] = search_region_y[i - 1] / scale_factor; } chan = chan_; // marshall int n = rows_*cols_; d = vector<int>(n, INT_MAX); // this can be initialized at the lowest level. // will have a vector for this.. M = M_ * (chan); // change M with number of channels.. num_iters = num_iters_; // initialize data // create pyramids for images and assignment vectors build_pyramid(img, num_levels); }
// API: open a fancy image struct fancy_image *fancy_image_open(char *filename, char *options) { // create return struct and its alias //struct fancy_image r[1]; struct fancy_image *r = xmalloc(sizeof*r); // I hate this malloc! struct FI *f = (void*)r; // process options parameter interpret_options(f, options); // if "c", do create the file if (f->option_creat) { if (filename_corresponds_to_tiffo(filename) || f->option_tw > 0) create_zero_tiff_file(filename, f->option_w, f->option_h, f->option_tw, f->option_th, f->option_spp, f->option_bps, f->option_fmt, true, f->option_compressed); else create_iio_file(filename, f->option_w, f->option_h, f->option_spp); } // read the image if (filename_corresponds_to_tiffo(filename)) { f->tiffo = true; tiff_octaves_init0(f->t, filename, f->megabytes,f->max_octaves); if (f->option_write) f->t->option_write = true; f->w = f->t->i->w; f->h = f->t->i->h; f->pd = f->t->i->spp; f->no = f->t->noctaves; } else { f->tiffo = false; f->x = iio_read_image_float_vec(filename, &f->w, &f->h, &f->pd); f->no = build_pyramid(f, f->max_octaves); strncpy(f->x_filename, filename, FILENAME_MAX); f->x_changed = false; } if (f->option_verbose) { fprintf(stderr, "FANCY IMAGE \"%s\"\n", filename); fprintf(stderr, "\tw = %d\n", f->w); fprintf(stderr, "\th = %d\n", f->h); fprintf(stderr, "\tpd = %d\n", f->pd); fprintf(stderr, "\tno = %d\n", f->no); fprintf(stderr, "\n"); fprintf(stderr, "\tmax_octaves= %d\n", f->max_octaves); fprintf(stderr, "\ttiffo = %d\n", f->tiffo); fprintf(stderr, "\tmegabytes = %g\n", f->megabytes); } // return image struct return r; }
// API: reload an image (works only for "small", images that can be read whole) void fancy_image_reload(struct fancy_image *fi) { struct FI *f = (void*)fi; if (!f->tiffo && !f->gdal) { int tmp_w, tmp_h, tmp_pd; float *tmp_x = iio_read_image_float_vec(f->x_filename, &tmp_w, &tmp_h, &tmp_pd); if (!tmp_x) { fprintf(stderr, "WARNING: could not reload image %s\n", f->x_filename); return; } if (tmp_w != f->w || tmp_h != f->h || tmp_pd != f->pd) { fprintf(stderr, "WARNING: image \"%s\" was resized" " from (%d %d %d) to (%d %d %d)\n", f->x_filename, f->w, f->h, f->pd, tmp_w, tmp_h, tmp_pd); } if (f->no > 1) free_pyramid(f); else free(f->x); f->x = tmp_x; f->w = tmp_w; f->h = tmp_h; f->pd = tmp_pd; f->no = build_pyramid(f, f->max_octaves); f->x_changed = true; } if (f->tiffo && !f->gdal) { // TODO: perform some sort of cache invalidation fprintf(stderr, "WARNING: tiffo reload not implemented!\n"); } }
void generic_read(struct FI *f, char *filename) { if (filename_corresponds_to_tiffo(filename)) { #ifdef FANCY_TIFF f->tiffo = true; tiff_octaves_init0(f->t, filename, f->megabytes,f->max_octaves); if (f->option_write) f->t->option_write = true; f->w = f->t->i->w; f->h = f->t->i->h; f->pd = f->t->i->spp; f->no = f->t->noctaves; #else assert(false); #endif } else if (!f->option_write && FORCE_GDAL()) { #ifdef FANCY_GDAL f->gdal = true; GDALAllRegister(); char buf[2*FILENAME_MAX]; snprintf(buf, 2*FILENAME_MAX, has_prefix(filename, "http://") || has_prefix(filename, "https://") ? "/vsicurl/%s" : "%s", filename); f->gdal_img = GDALOpen(buf, GA_ReadOnly); fprintf(stderr, "gdal_dataset = %p\n", f->gdal_img); f->pd = GDALGetRasterCount(f->gdal_img); f->w = GDALGetRasterXSize(f->gdal_img); f->h = GDALGetRasterYSize(f->gdal_img); f->no = 1; for (int i = 0; i < f->pd; i++) f->gdal_band[i] = GDALGetRasterBand(f->gdal_img, i+1); #else assert(false); #endif } else { f->x = iio_read_image_float_vec(filename, &f->w, &f->h, &f->pd); f->no = build_pyramid(f, f->max_octaves); snprintf(f->x_filename, FILENAME_MAX, "%s", filename); f->x_changed = false; } }
void Slic::reset_image(const vector<unsigned char>& img) { // warning! if the new array has different dimensions (rows/cols/chans).. // ..well there are no checks for that. build_pyramid(img, num_levels); }